package com.ryze.common.dubbo.filter;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
import org.apache.dubbo.rpc.service.GenericService;

/**
 * 服务消费者日志拦截器，打印dubbo调用的入参和响应
 *
 * @author raise.wang
 */
@Slf4j
@Activate(group = {CommonConstants.CONSUMER})
public class ConsumerLogFilter implements Filter {
    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        //打印入参
        String invokePath = RpcContext.getContext().getLocalHost()
                + ":"
                + RpcContext.getContext().getLocalPort()
                + " -> "
                + RpcContext.getContext().getRemoteHost()
                + ":"
                + RpcContext.getContext().getRemotePort();

        if(log.isDebugEnabled()){
            String args = JSON.toJSONStringWithDateFormat(invocation.getArguments(),"yyyy-MM-dd HH:mm:ss");
            log.info("consumer request, interface={}, method={}, args={}.[{}]",
                    invocation.getInvoker().getInterface().getName(),
                    invocation.getMethodName(),
                    args,
                    invokePath);
        }else {
            log.info("consumer request, interface={}, method={}.[{}]",
                    invocation.getInvoker().getInterface().getName(),
                    invocation.getMethodName(),
                    invokePath);
        }
        //开始时间
        long startTime = System.currentTimeMillis();
        //执行接口调用逻辑
        Result result = invoker.invoke(invocation);
        //调用耗时
        long elapsed = System.currentTimeMillis() - startTime;
        //如果发生异常，则打印异常日志
        if (result.hasException() && invoker.getInterface() != GenericService.class) {
            log.info("consumer request fail.[{}]",invokePath);
        } else {
            if(log.isDebugEnabled()) {
                String res = JSON.toJSONStringWithDateFormat(result.getValue(), "yyyy-MM-dd HH:mm:ss");
                log.info("consumer response, interface={}, method={}, result={}, spend={}ms.[{}]",
                        invocation.getInvoker().getInterface().getName(),
                        invocation.getMethodName(),
                        res,
                        elapsed,
                        invokePath);
            }else{
                log.info("consumer response, interface={}, method={}, spend={}ms.[{}]",
                        invocation.getInvoker().getInterface().getName(),
                        invocation.getMethodName(),
                        elapsed,
                        invokePath);
            }
        }
        //返回结果响应数据
        return result;
    }
}